org     0x7c00;             ; 这是一个物理内存地址
                            ; org表示从这个地址开始写

jmp     entry               ; 跳转命令，占2字节(每个平台的情况不一样)
db      0x90                ; db表示分配一个字节并赋值为0x90, 即(char*)(0x7c00+2) = 0x90
DB      "OSKERNEL"          ; DB和db一个意思。类似于strcpy((char*)(0x7c00+2+1), "OSKERNEL");
                            ; 注意：内存中并没有给'\0'分配空间!
DW      512                 ; DW表示分配一个字(16bit)并赋值, 即(uint16_t*)(0x7c00+2+1+8) = 512
DB      1
DW      1
DB      2
DW      224
DW      0xf0
DW      9
DW      18
DW      2
DD      0                   ; DD表示分配一个双字并赋值(这里是32bit)
DD      2880
DB      0,0,0x29
DB      "MyFirstOS"
DB      "FAT12"
RESB    18                  ; 把接下来的18个字节内存空间全部初始化为0

; ax是两字节长度的寄存器，可以分为ah和al分别访问其高低字节。
; 类似于 char ax[2]; 则al = ax[0]; ah = ax[1];
entry:
    mov     ax, 0           ; ax = 0
    mov     ss, ax
    mov     ds, ax
    mov     es, ax
    mov     si, msg         ; 将msg内存的起始地址赋值给si寄存器

putloop:
    mov     al, [si]        ; [si]表示读取si寄存器内存地址处的一个字节,即al = *(char*)si
    add     si, 1           ; si += 1
    cmp     al, 0           ; 
    je      fin             ; if(al == 0) goto fin;
    mov     ah, 0x0e
    mov     bx, 15
    int     0x10            ; 调用中断，中断就是bios提供给汇编的库函数。
                            ; 把所有库函数放在中断表中并编号，0x10表示执行第0x10号中断。
                            ; 0x10号中断用于输出字符到屏幕上，要输出成功需要满足以下条件：
                            ; 1. ah必须为0x0e，al为要输出的字符，
                            ; 2. bh必须为0，bl用于决定字符颜色。
    jmp     putloop

fin:
    HLT                     ; halt, 即CPU进入休眠状态。可通过点击等事件唤醒CPU往下执行
    jmp     fin

msg:                            ; 定义了一段内存，类似于char* msg = "\n\nHello, World\n";
    DB      0x0a, 0x0a
    db      "Hello, World!"
    db      0x0a
    db      0

